package com.samehope.ar.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.samehope.ar.constant.*;
import com.samehope.ar.dto.TaskItemReplyParam;
import com.samehope.ar.entity.*;
import com.samehope.ar.mapper.TaskItemMapper;
import com.samehope.ar.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.samehope.ar.util.SessionUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 巡检项快照 服务实现类
 * </p>
 *
 * @author ZhangLuo
 * @since 2019-12-31
 */
@Slf4j
@Service
public class TaskItemServiceImpl extends ServiceImpl<TaskItemMapper, TaskItem> implements ITaskItemService {

    @Autowired
    private ITaskPointService taskPointService;

    @Autowired
    private ITaskNormalService taskNormalService;

    @Autowired
    private ITaskItemChildService itemChildService;

    @Autowired
    private ITaskItemReplyService itemReplyService;

    @Autowired
    private IDeviceRecordService deviceRecordService;

    /**
     * 回复巡检项
     * 1. 只判断巡检项是否已经被检查了, 不强制校验点或线路必须某个人全程执行完成
     * 2. 点位, 巡检项的执行人, 只按最后一次执行人记录
     * @param param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void reply(TaskItemReplyParam param) {

        final LocalDateTime now = LocalDateTime.now();

        final Long taskItemId = param.getTaskItemId();

        // 巡检项
        TaskItem taskItem = this.baseMapper.findByProjectAndTaskItem(SessionUtil.getProjectId(), taskItemId);
        if (taskItem == null) {
            throw new IllegalArgumentException("任务巡检项不存在");
        }

        TaskItemChild itemChild = null;
        // 逻辑校验
        if (TaskStatusEnum.OVER.getCode().equals(taskItem.getTaskItemStatus())) {
            throw new IllegalArgumentException("该巡检项已经被处理过了");
        }
        if (SubjectTypeEnum.CHOICE.getCode().equals(taskItem.getSubjectType()) && param.getTaskItemChildIds() == null) {
            throw new IllegalArgumentException("必须选择一个选项");
        }

        Integer replyStatus = 0;

        // 判定回复状态
        if (SubjectTypeEnum.GAP_FILLING.getCode().equals(taskItem.getSubjectType())) {
            // 填空题, 默认正常, 无法判断是否异常
        } else if (SubjectTypeEnum.CHOICE.getCode().equals(taskItem.getSubjectType())) {
            final String taskItemChildIds = param.getTaskItemChildIds();
            final String[] split = taskItemChildIds.split(",");
            for (int i = 0; i < split.length; i++) {
                itemChild = itemChildService.getByItemAndChild(param.getTaskItemId(), Long.valueOf(split[i]));
                if (itemChild == null) {
                    throw new IllegalArgumentException("巡检子项不存在");
                }

                if (itemChild.getTrueOrFalse().equals("false")) {
                    replyStatus = 1;
                    break;
                }
            }

        } else if (SubjectTypeEnum.TRUE_OR_FALSE.getCode().equals(taskItem.getSubjectType())) {
            if (param.getReplyContent().equals("false")) {
                replyStatus = 1;
            } else if (param.getReplyContent().equals("true")) {

            } else {
                throw new IllegalArgumentException("判断题的回复只允许: true or false");
            }
        } else if (SubjectTypeEnum.RANGE.getCode().equals(taskItem.getSubjectType())) {
            QueryWrapper<TaskItemChild> qw = new QueryWrapper<>();
            qw.eq("task_item_id", taskItemId);
            qw.eq("del_flag", DelFlagEnum.NORMAL.getCode());
            final TaskItemChild one = itemChildService.getOne(qw);

            String replyContent = param.getReplyContent();
            if (replyContent.matches("[0-9]+[.][0-9]+")) {
                BigDecimal bigDecimal = new BigDecimal(param.getReplyContent());
                if (bigDecimal.compareTo(one.getUpperLimit()) == 1 || bigDecimal.compareTo(one.getLowerLimit()) == -1) {
                    replyStatus = 1;
                }
            }
        } else {
            log.error("巡检项问题类型异常, 类型值: {} 无法识别", taskItem.getSubjectType());
            throw new IllegalArgumentException("巡检项问题类型异常");
        }


        if (taskItem.getIsPhoto() == 1 && StringUtils.isBlank(param.getPicUrl())) {
            throw new IllegalArgumentException("当前检查项需要拍照");
        }
        if (taskItem.getIsVideo() == 1 && StringUtils.isBlank(param.getVideoUrl())) {
            throw new IllegalArgumentException("当前检查项需要录像");
        }
        if (taskItem.getIsRemark() == 1 && StringUtils.isBlank(param.getReplyDesc())) {
            throw new IllegalArgumentException("当前检查项需要备注");
        }

        // 巡检点
        TaskPoint taskPoint = taskPointService.getById(taskItem.getTaskPointId());
        // 巡检任务
        TaskNormal taskNormal = taskNormalService.getById(taskPoint.getTaskId());

        // 逻辑校验
        if (taskNormal.getIsRecordLocation() == 1 && StringUtils.isBlank(param.getCoordinate())) {
            throw new IllegalArgumentException("当前检查项需要上传GPS位置");
        }

        // 如果还是未执行状态, 需要记录实际执行时间
        if (TaskStatusEnum.NEW.getCode().equals(taskNormal.getTaskStatus())) {
            taskNormal.setRealStartDate(now);
        }
        taskNormal.setRealExecBy(SessionUtil.getUserId());
        taskNormal.setUpdateBy(SessionUtil.getUserId());
        taskNormal.setUpdateDate(now);
        taskNormal.setTaskStatus(TaskStatusEnum.LOADING.getCode());

        // 获取当前任务未执行完成的巡检点
        QueryWrapper<TaskPoint> var2 = new QueryWrapper<>();
        var2.eq("task_id", taskNormal.getId());
        var2.notIn("task_point_status", PointStatusEnum.UNCHECK_OVER.getCode(), PointStatusEnum.OVER.getCode());
        var2.eq("del_flag", DelFlagEnum.NORMAL.getCode());
        final List<TaskPoint> taskPoints = taskPointService.list(var2);

        if (taskPoints.size() == 1) {
            // 获取当前任务未执行的检查项(检查项只有未执行和完成2个状态, 无中间状态)
            QueryWrapper<TaskItem> var1 = new QueryWrapper<>();
            var1.eq("task_point_id", taskPoints.get(0).getId());
            var1.eq("task_item_status", ItemStatusEnum.NEW.getCode());
            var1.eq("del_flag", DelFlagEnum.NORMAL.getCode());
            final List<TaskItem> taskItems = this.list(var1);

            // 如果当前未执行的点和巡检项都只有1个, 那么就是当前需要处理的, 该任务也就结束了
            if (taskItems.size() == 1) {
                taskNormal.setTaskStatus(TaskStatusEnum.OVER.getCode());
            }
        }

        taskNormalService.updateById(taskNormal);

        // 更新点位
        taskPoint.setExecBy(SessionUtil.getUserId());
        if (taskPoint.getRealStartDate() == null) {
            taskPoint.setRealStartDate(now);
        }
        taskPoint.setTaskPointStatus(PointStatusEnum.LOADING.getCode());
        taskPoint.setUpdateBy(SessionUtil.getUserId());
        taskPoint.setUpdateDate(now);

        if (TaskStatusEnum.OVER.getCode().equals(taskNormal.getTaskStatus())) {
            taskPoint.setTaskPointStatus(PointStatusEnum.OVER.getCode());
            taskPoint.setRealEndDate(now);
        }
        taskPointService.updateById(taskPoint);

        // 更新巡检项
        taskItem.setExecBy(SessionUtil.getUserId());
        taskItem.setRealStartDate(now);
        taskItem.setRealEndDate(now);
        taskItem.setTaskItemStatus(TaskStatusEnum.OVER.getCode());
        this.updateById(taskItem);

        // 保存回复
        TaskItemReply itemReply = new TaskItemReply();
        itemReply.setCompanyId(SessionUtil.getCompanyId());
        itemReply.setTaskItemId(taskItemId);
        itemReply.setReplyContent(param.getReplyContent());
        itemReply.setPicUrl(param.getPicUrl());
        itemReply.setVideoUrl(param.getVideoUrl());
        itemReply.setReplyDesc(param.getReplyDesc());
        itemReply.setCreateBy(SessionUtil.getUserId());
        itemReply.setCreateDate(now);
        itemReply.setReplyStatus(replyStatus);
        itemReplyService.save(itemReply);

        // 保存使用记录
        DeviceRecord record = new DeviceRecord();
        record.setDeviceId(SessionUtil.getDeviceId());
        record.setCompanyId(SessionUtil.getCompanyId());
        record.setUserId(SessionUtil.getUserId());
        record.setRecord(MessageFormat.format("用户: {0}, 完成了任务: {1}, 巡检点: {2}, 巡检项: {3}的检查",
                SessionUtil.getUser().getMobile(), taskNormal.getTaskName(), taskPoint.getPointName(), taskItem.getPatrolItemName()));
        record.setCreateBy(SessionUtil.getUserId());
        record.setCreateDate(now);
        deviceRecordService.save(record);
    }
}
